package io.gitee.wl4837.alatool.core.util;

import io.gitee.wl4837.alatool.core.getter.MethodBaseFieldGetter;

import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author wangliang
 */
public class ClassUtil {

    /**
     * 获取某个类中声明的所有字段，包括公有、私有、受保护的字段，但不包括继承的字段。
     *
     * @param object 获取对象
     * @return 字段数组
     */
    public static Field[] getDeclaredFields(Object object) {
        return getDeclaredFields(object.getClass());
    }

    /**
     * 获取某个类中声明的所有字段，包括公有、私有、受保护的字段，包括继承的字段。
     *
     * @param object 获取对象
     * @return 字段数组
     */
    public static Field[] getAllDeclaredFields(Object object) {
        return getAllDeclaredFields(object.getClass());
    }

    /**
     * 获取某个类所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param object 获取对象
     * @return 字段数组
     */
    public static Field[] getFields(Object object) {
        return getFields(object.getClass());
    }

    /**
     * 获取某个类及其父类中所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param object 对象
     * @return 字段数组
     */
    public static Field[] getAllFields(Object object) {
        return getAllFields(object.getClass());
    }

    /**
     * 获取某个类中声明的所有字段，包括公有、私有、受保护的字段，但不包括继承的字段。
     *
     * @param clazz 类
     * @return 字段数组
     */
    public static Field[] getDeclaredFields(Class<?> clazz) {
        return clazz.getDeclaredFields();
    }

    /**
     * 获取某个类中声明的所有字段，包括公有、私有、受保护的字段，包括继承的字段。
     *
     * @param clazz 类
     * @return 字段数组
     */
    public static Field[] getAllDeclaredFields(Class<?> clazz) {
        Class<?> next = clazz;
        List<Field> fields = new ArrayList<>();
        while (null != next && next != Object.class) {
            fields.addAll(Arrays.asList(next.getDeclaredFields()));
            next = next.getSuperclass();
        }
        return fields.toArray(new Field[0]);
    }

    /**
     * 获取某个类所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param clazz 类
     * @return 字段数组
     */
    public static Field[] getFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        Field[] singleFields = clazz.getFields();
        for (Field singleField : singleFields) {
            if (singleField.getDeclaringClass().equals(clazz)) {
                fields.add(singleField);
            }
        }
        return fields.toArray(new Field[0]);
    }

    /**
     * 获取某个类及其父类中所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param clazz 类
     * @return 字段数组
     */
    public static Field[] getAllFields(Class<?> clazz) {
        return clazz.getFields();
    }

    /**
     * 获取某个类中声明的字段，包括公有、私有、受保护的字段，但不包括继承的字段。
     *
     * @param object 对象
     * @param name   属性名称
     * @return 字段
     */
    public static Field getDeclaredField(Object object, String name) {
        return getDeclaredField(object.getClass(), name);
    }

    /**
     * 获取某个类中声明的字段，包括公有、私有、受保护的字段，包括继承的字段。
     *
     * @param object 对象
     * @param name   属性名称
     * @return 字段
     */
    public static Field getAllDeclaredField(Object object, String name) {
        return getAllDeclaredField(object.getClass(), name);
    }

    /**
     * 获取某个类所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param object                对象
     * @param methodBaseFieldGetter 获取对象
     * @return 字段
     * @param <T> 属性类
     * @param <R> 属性返回值
     */
    public static <T, R> Field getField(T object, MethodBaseFieldGetter<T, R> methodBaseFieldGetter) {
        return getField(object.getClass(), methodBaseFieldGetter.getFieldName());
    }

    /**
     * 获取某个类及其父类中所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param object                对象
     * @param methodBaseFieldGetter 获取对象
     * @return 字段
     * @param <T> 属性类
     * @param <R> 属性返回值
     */
    public static <T, R> Field getAllField(T object, MethodBaseFieldGetter<T, R> methodBaseFieldGetter) {
        return getAllField(object.getClass(), methodBaseFieldGetter.getFieldName());
    }

    /**
     * 获取某个类中声明的字段，包括公有、私有、受保护的字段，但不包括继承的字段。
     *
     * @param object                对象
     * @param methodBaseFieldGetter 获取对象
     * @return 字段
     * @param <T> 属性类
     * @param <R> 属性返回值
     */
    public static <T, R> Field getDeclaredField(T object, MethodBaseFieldGetter<T, R> methodBaseFieldGetter) {
        return getDeclaredField(object.getClass(), methodBaseFieldGetter.getFieldName());
    }

    /**
     * 获取某个类中声明的字段，包括公有、私有、受保护的字段，包括继承的字段。
     *
     * @param object                对象
     * @param methodBaseFieldGetter 获取对象
     * @return 字段
     * @param <T> 属性类
     * @param <R> 属性返回值
     */
    public static <T, R> Field getAllDeclaredField(T object, MethodBaseFieldGetter<T, R> methodBaseFieldGetter) {
        return getAllDeclaredField(object.getClass(), methodBaseFieldGetter.getFieldName());
    }

    /**
     * 获取某个类中声明的字段，包括公有、私有、受保护的字段，包括继承的字段。
     *
     * @param clz                   类
     * @param methodBaseFieldGetter 获取对象
     * @return 字段
     * @param <T> 属性类
     * @param <R> 属性返回值
     */
    public static <T, R> Field getAllDeclaredField(Class<T> clz, MethodBaseFieldGetter<T, R> methodBaseFieldGetter) {
        return getAllDeclaredField(clz, methodBaseFieldGetter.getFieldName());
    }

    /**
     * 获取某个类所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param object 对象
     * @param name   获取对象名称
     * @return 字段
     */
    public static Field getField(Object object, String name) {
        return getField(object.getClass(), name);
    }

    /**
     * 获取某个类及其父类中所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param object 对象
     * @param name   获取对象名称
     * @return 字段
     */
    public static Field getAllField(Object object, String name) {
        return getAllField(object.getClass(), name);
    }

    /**
     * 获取某个类中声明的字段，包括公有、私有、受保护的字段，但不包括继承的字段。
     *
     * @param clazz 类
     * @param name  获取对象名称
     * @return 字段
     */
    public static Field getDeclaredField(Class<?> clazz, String name) {
        Field[] fields = getDeclaredFields(clazz);
        for (Field field : fields) {
            if (field.getName().equals(name)) {
                return field;
            }
        }
        return null;
    }

    /**
     * 获取某个类中声明的字段，包括公有、私有、受保护的字段，包括继承的字段。
     *
     * @param clazz 类
     * @param name  获取对象名称
     * @return 字段
     */
    public static Field getAllDeclaredField(Class<?> clazz, String name) {
        Field[] fields = getAllDeclaredFields(clazz);
        for (Field field : fields) {
            if (field.getName().equals(name)) {
                return field;
            }
        }
        return null;
    }

    /**
     * 获取某个类所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param clazz 类
     * @param name  获取对象名称
     * @return 字段
     */
    public static Field getField(Class<?> clazz, String name) {
        Field[] fields = getFields(clazz);
        for (Field field : fields) {
            if (field.getName().equals(name)) {
                return field;
            }
        }
        return null;
    }

    /**
     * 获取某个类及其父类中所有的公有字段。公有字段是指用public修饰的字段。
     *
     * @param clazz 类
     * @param name  获取对象名称
     * @return 字段
     */
    public static Field getAllField(Class<?> clazz, String name) {
        Field[] fields = getAllFields(clazz);
        for (Field field : fields) {
            if (field.getName().equals(name)) {
                return field;
            }
        }
        return null;
    }

}
